package clustering;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;

import preprocess.XMLDoc;
import similarity.Similarity;

@SuppressWarnings( { "unchecked", "unused" })
public class HierarchyClustering extends Clustering
{
    public HierarchyClustering(Similarity similarity)
    {
        super(similarity);
    }

    @Override
    public List<List<XMLDoc>> cluster(List<XMLDoc> list, int count)
    {
        HashSet<HashSet<XMLDoc>> resultSet = new HashSet<HashSet<XMLDoc>>();
        for (XMLDoc doc : list)
        {
            HashSet<XMLDoc> set = new HashSet<XMLDoc>();
            set.add(doc);
            resultSet.add(set);
        }
        // 一次层次聚类
        while (resultSet.size() > count)
        {
            HashSet<XMLDoc>[] array = resultSet.toArray(new HashSet[0]);
            if (array.length == 10)
            {
                int a = 0;
                a++;
            }
            double maxSimilarity = -1;
            HashSet<XMLDoc> set1 = null, set2 = null;
            for (int i = 0; i < array.length; i++)
            {
                for (int j = i + 1; j < array.length; j++)
                {
                    double similarity = calcSimilarity(array[i], array[j]);
                    if (similarity > maxSimilarity)
                    {
                        maxSimilarity = similarity;
                        set1 = array[i];
                        set2 = array[j];
                    }
                }
            }
            // }
            // double[][] simArray = new double[array.length][array.length];
            // for (int i = 0; i < array.length; i++)
            // {
            // for (int j = 0; j < array.length; j++)
            // {
            // simArray[i][j] = calcSimilarity(array[i], array[j]);
            // simArray[i][j] = (int) (simArray[i][j] * 100) / 100.0;
            // }
            // }
            // System.out.printf("[");
            // for (HashSet<XMLDoc> set : array)
            // {
            // System.out.printf("%10s", set.toString());
            // }
            // System.out.printf("]\r\n");
            // for (int i = 0; i < array.length; i++)
            // {
            // System.out.printf("[");
            // for (double val : simArray[i])
            // {
            // System.out.printf("%10f", val);
            // }
            // System.out.printf("]\r\n");
            // }
            System.out.println(maxSimilarity);
            System.out.println(set1);
            System.out.println(set2);
            resultSet.remove(set1);
            resultSet.remove(set2);
            set1.addAll(set2);
            resultSet.add(set1);
        }
        List<List<XMLDoc>> result = new ArrayList<List<XMLDoc>>();
        for (HashSet<XMLDoc> set : resultSet)
        {
            List<XMLDoc> l = new ArrayList<XMLDoc>(set);
            result.add(l);
        }
        return result;
    }

    // /**
    // * 最长距离法求聚类相似度
    // *
    // * @param set1
    // * @param set2
    // * @return
    // */
    // private double calcSimilarity(HashSet<XMLDoc> set1, HashSet<XMLDoc> set2)
    // {
    // double minSimilarity = Double.MAX_VALUE;
    // for (XMLDoc doc1 : set1)
    // {
    // for (XMLDoc doc2 : set2)
    // {
    // double sim = similarity.calcSimilarity(doc1, doc2);
    // minSimilarity = Math.min(sim, minSimilarity);
    // }
    // }
    // return minSimilarity;
    // }

    /**
     * 平均距离法求聚类相似度
     * 
     * @param set1
     * @param set2
     * @return
     */
    private double calcSimilarity(HashSet<XMLDoc> set1, HashSet<XMLDoc> set2)
    {
        double total = 0;
        // int count = 0;
        for (XMLDoc doc1 : set1)
        {
            for (XMLDoc doc2 : set2)
            {
                double sim = similarity.calcSimilarity(doc1, doc2);
                if (sim < 0)
                    System.err.println(doc1.getDocID() + " " + doc2.getDocID()
                            + ":" + sim);
                total += sim * sim;
                // count++;
            }
        }
        total = total / (set1.size() * set2.size());
        total = Math.sqrt(total);
        return total;
    }

    // /**
    // * 最短距离法求聚类相似度，取相似度最大的两个XMLDoc的相似度作为两个聚类的相似度
    // *
    // * @param set1
    // * @param set2
    // * @return
    // */
    // private double calcSimilarity(HashSet<XMLDoc> set1, HashSet<XMLDoc> set2)
    // {
    // double maxSimilarity = -1;
    // for (XMLDoc doc1 : set1)
    // {
    // for (XMLDoc doc2 : set2)
    // {
    // double sim = similarity.calcSimilarity(doc1, doc2);
    // maxSimilarity = Math.max(sim, maxSimilarity);
    // }
    // }
    // return maxSimilarity;
    // }
}
